package main

import (
	"flag"
	"fmt"
	"gitee.com/zackeus/go-boot/cron"
	"gitee.com/zackeus/go-boot/cron/core"
	etcddriver "gitee.com/zackeus/go-boot/cron/drive/etcd"
	"gitee.com/zackeus/go-zero/core/logx"
	"github.com/google/uuid"
	"go.etcd.io/etcd/client/pkg/v3/transport"
	clientv3 "go.etcd.io/etcd/client/v3"
	"log"
	"os"
	"os/signal"
	"reflect"
	"strconv"
	"syscall"
	"time"
)

var (
	serverName = flag.String("server_name", "server", "the server name of dcron in this process")
	subId      = flag.String("sub_id", "1", "this process sub id in this server")
	jobNumber  = flag.Int("jobnumber", 3, "there number of cron job")

	hosts       = []string{"etcd.node1.server:2379"}
	caCertFile  = "/Users/zackeus/server-dev/etcd/dev/ca.pem"
	certFile    = "/Users/zackeus/server-dev/etcd/dev/certs-client.d/root/client-cert.pem"
	certKeyFile = "/Users/zackeus/server-dev/etcd/dev/certs-client.d/root/client-key.pem"
)

func initEtcdCli() (*clientv3.Client, error) {
	/* 证书 */
	tlsInfo := transport.TLSInfo{
		TrustedCAFile: caCertFile,
		CertFile:      certFile,
		KeyFile:       certKeyFile,
	}
	tlsConfig, err := tlsInfo.ClientConfig()
	if err != nil {
		return nil, err
	}

	/* 连接实例化 */
	return clientv3.New(clientv3.Config{
		Endpoints:   hosts,
		TLS:         tlsConfig,
		DialTimeout: 5 * time.Second,
	})
}

type (
	Test struct{}

	WriteJob struct {
		Id int
	}
)

func (t *Test) TestJob(id int) core.Job {
	return &WriteJob{id}
}

func (wj *WriteJob) Run() {
	log.Print("run ********************************************************************************************")
	log.Printf("id=%d, sub_id=%s, time=%s, append string=%s\n", wj.Id, *subId, time.Now().String(), uuid.New().String())
}

func main() {
	if err := logx.SetUp(logx.LogConf{Mode: "console", Encoding: "plain"}); err != nil {
		fmt.Println(err)
		return
	}

	flag.Parse()
	var err error

	cli, err := initEtcdCli()
	if err != nil {
		log.Fatal(err)
		return
	}
	driver := etcddriver.NewDriver("test", cli)

	value := reflect.ValueOf(&Test{})
	f := value.MethodByName("TestJob")

	c, err := cron.New(cron.WithDriver(driver), cron.WithHashReplicas(30))
	for i := 1; i <= *jobNumber; i++ {
		/* 使用反射生成job 可用于管理界面参数生成job */
		v := f.Call([]reflect.Value{reflect.ValueOf(i)})
		err = c.AddJob("write-task"+strconv.Itoa(i), "* * * * *", v[0].Interface().(core.Job))
		if err != nil {
			panic(err)
		}
	}
	_ = c.Start()

	signals := make(chan os.Signal, 1)
	signal.Notify(signals, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGTERM, syscall.SIGINT)
	<-signals
	c.Stop()
}
